package com.tanhua.server.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.dubbo.server.api.UserLikeApi;
import com.tanhua.dubbo.server.api.UserLocationApi;
import com.tanhua.dubbo.server.pojo.RecommendUser;
import com.tanhua.dubbo.server.vo.PageInfo;
import com.tanhua.dubbo.server.vo.UserLocationVo;
import com.tanhua.server.enums.SexEnum;
import com.tanhua.server.pojo.Question;
import com.tanhua.server.pojo.User;
import com.tanhua.server.pojo.UserInfo;
import com.tanhua.server.utils.UserThreadLocal;
import com.tanhua.server.vo.NearUserVo;
import com.tanhua.server.vo.PageResult;
import com.tanhua.server.vo.RecommendUserQueryParam;
import com.tanhua.server.vo.TodayBest;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@Service
public class TodayBestService {

    @Autowired
    private UserService userService;

    @Autowired
    private RecommendUserService recommendUserService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private IMService imService;

    @Reference(version = "2.0.0") //2.0.0是ES版本的实现,1.0.0是mongodb的实现
    private UserLocationApi userLocationApi;

    @Reference(version = "1.0.0")
    private UserLikeApi userLikeApi;

    @Value("${tanhua.sso.default.user}")
    private Long defaultUserId;

    @Value("${tanhua.sso.default.recommend.users}")
    private String defaultRecommendUsers;

    @Value("${tanhua.sso.url}")
    private String ssoUrl;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Autowired
    private RestTemplate restTemplate;

    public TodayBest queryTodayBest() {
        //通过token获取当前登录用户的userId
        User user = UserThreadLocal.get();

        //查询今日佳人
        TodayBest todayBest = recommendUserService.queryTodayBest(user.getId());//该方法返回的todayBest中已填充的个人信息有userId&fateValue缘分值

        if (null == todayBest) {
            //没有查询到推荐用户,给出默认推荐用户并固定缘分值
            todayBest = new TodayBest();
            todayBest.setId(defaultUserId);
            todayBest.setFateValue(80L);
        }

        //补全个人信息:需要先根据今日佳人的userId去查询其在userInfo中的其他个人信息
        UserInfo userInfo = userInfoService.queryUserInfoByUserId(todayBest.getId());
        if (null == userInfo) { //理论上不可能
            return null;
        }

        //缘分值在recommendUserService.queryTodayBest的时候已经拿到了,因此不需要另外设定,但如果是默认推荐的用户需要给缘分值
        todayBest.setAvatar(userInfo.getLogo());
        todayBest.setNickname(userInfo.getNickName());
        todayBest.setTags(StringUtils.split(userInfo.getTags(), ","));
        todayBest.setGender(userInfo.getSex().getValue() == 1 ? "man" : "woman");
        todayBest.setAge(userInfo.getAge());

        return todayBest;
    }

    public PageResult queryRecommendation(RecommendUserQueryParam queryParam) {
        //通过token获取当前登录用户的userId
        User user = UserThreadLocal.get();

        PageResult pageResult = new PageResult(); //PageResult类中已给成员变量初始化赋值,此处只给必要的成员变量做二次赋值
        pageResult.setPage(queryParam.getPage());
        pageResult.setPagesize(queryParam.getPagesize());

        PageInfo<RecommendUser> pageInfo = recommendUserService.queryRecommendUserList(user.getId(), queryParam.getPage(), queryParam.getPagesize());
        List<RecommendUser> records = pageInfo.getRecords();
        //未查询到推荐到用户列表
        if (CollectionUtils.isEmpty(records)) {
            String[] defaultRecommendUserIds = StringUtils.split(defaultRecommendUsers, ",");
            for (String defaultRecommendUserId : defaultRecommendUserIds) {
                RecommendUser recommendUser = new RecommendUser(); //id和date属性不需要,不赋值
                recommendUser.setUserId(Long.valueOf(defaultRecommendUserId));
                recommendUser.setToUserId(user.getId());
                recommendUser.setScore(RandomUtils.nextDouble(70, 98));
                records.add(recommendUser);
            }
        }

        //填充个人信息

        //1.收集推荐用户的id(采用set集合进行去重,避免因测试造成数据库有很多脏数据)
        HashSet<Long> userIds = new HashSet<>();
        for (RecommendUser record : records) {
            userIds.add(record.getUserId());
        }

        //2.根据收集到的推荐用户id查询tb_user_info表中该用户的其他信息
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        //用户id参数
        wrapper.in("user_id", userIds);
        //性别参数
//        if (StringUtils.isNoneEmpty(queryParam.getGender())) { //客户端有传递当前用户的性别,则增加性别参数查询
//            wrapper.eq("sex", StringUtils.equals(queryParam.getGender(), "man") ? 1 : 2);
//        }
//        //city参数
//        if (StringUtils.isNoneEmpty(queryParam.getCity())) {
//            wrapper.like("city", queryParam.getCity());
//        }
//        //age参数
//        if (queryParam.getAge() != null) {
//            //设置推荐用户的年龄不能大于登录用户
//            wrapper.le("age", queryParam.getAge());
//        }

        //此处方法的参数不能确定(相对复杂),需要我们自己构造一个QueryWrapper,将条件汇总给到userInfoService
        List<UserInfo> userInfoList = userInfoService.queryUserInfoList(wrapper);

        if (CollectionUtils.isEmpty(userInfoList)) {
            //未查询到用户的基本信息
            return pageResult;
        }

        ArrayList<TodayBest> todayBests = new ArrayList<>();

        for (UserInfo userInfo : userInfoList) {
            TodayBest todayBest = new TodayBest();
            todayBest.setId(userInfo.getUserId());
            todayBest.setAvatar(userInfo.getLogo());
            todayBest.setNickname(userInfo.getNickName());
            todayBest.setTags(StringUtils.split(userInfo.getTags(), ","));
            todayBest.setGender(userInfo.getSex().getValue() == 1 ? "man" : "woman");
            todayBest.setAge(userInfo.getAge());
            //缘分值
            for (RecommendUser record : records) {
                if (record.getUserId().longValue() == userInfo.getUserId().longValue()) {
                    double score = Math.floor(record.getScore());
                    todayBest.setFateValue(Double.valueOf(score).longValue());//缘分值需去除小数
                    break;
                }
            }

            todayBests.add(todayBest);
            //按照缘分值进行倒序排序
            Collections.sort(todayBests, ((o1, o2) -> new Long(o2.getFateValue() - o1.getFateValue()).intValue()));
        }
        pageResult.setItems(todayBests);
        return pageResult;
    }

    public TodayBest queryTodayBest(Long userId) {

        User user = UserThreadLocal.get();

        TodayBest todayBest = new TodayBest();
        //补全信息
        UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(userId);
        todayBest.setId(userId);
        todayBest.setAge(userInfo.getAge());
        todayBest.setAvatar(userInfo.getLogo());
        todayBest.setGender(userInfo.getSex().name().toLowerCase());
        todayBest.setNickname(userInfo.getNickName());
        todayBest.setTags(StringUtils.split(userInfo.getTags(), ','));

        double score = this.recommendUserService.queryScore(userId, user.getId());
        if (score == 0) {
            score = 98; //默认分值
        }

        todayBest.setFateValue(Double.valueOf(score).longValue());

        return todayBest;
    }

    public String queryQuestion(Long userId) {
        Question question = this.questionService.queryQuestion(userId);
        if (null != question) {
            return question.getTxt();
        }
        return "";
    }

    public Boolean replyQuestion(Long userId, String reply) {

        User user = UserThreadLocal.get();
        UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(user.getId());

        //构建要发送的消息内容
        Map<String, Object> msg = new HashMap<>();
        msg.put("userId", user.getId().toString());
        msg.put("nickname", userInfo.getNickName());
        msg.put("strangerQuestion", this.queryQuestion(userId));
        msg.put("reply", reply);

        try {
            String msgStr = MAPPER.writeValueAsString(msg);//将map序列化为String类型的JSON数据

            String targetUrl = this.ssoUrl + "/user/huanxin/messages";//对应sso模块的HuanXinController的sendMsg方法url

            //设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); //form表单提交

            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();//传递参数,对应sso模块的HuanXinController的sendMsg方法的形参
            params.add("target", userId.toString());
            params.add("msg", msgStr);

            HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);

            ResponseEntity<Void> responseEntity = this.restTemplate.postForEntity(targetUrl, httpEntity, Void.class);

            return responseEntity.getStatusCodeValue() == 200;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    public List<NearUserVo> queryNearUser(String gender, String distance) {

        User user = UserThreadLocal.get();

        //查询当前登录用户的地理位置
        UserLocationVo userLocationVo = userLocationApi.queryUserLocationByUserId(user.getId());
        Double longitude = userLocationVo.getLongitude();
        Double latitude = userLocationVo.getLatitude();
        //查询登录用户附近好友
        List<UserLocationVo> userLocationVoList = userLocationApi.queryUserFromLocation(longitude, latitude, Integer.valueOf(distance));

        if (CollectionUtils.isEmpty(userLocationVoList)) {
            return Collections.emptyList();
        }

        HashSet<Long> userIds = new HashSet<>();
        for (UserLocationVo locationVo : userLocationVoList) {
            userIds.add(locationVo.getUserId());
        }

        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", userIds);
        if (StringUtils.equalsIgnoreCase(gender, "man")) {
            queryWrapper.eq("sex", SexEnum.MAN);
        } else if (StringUtils.equalsIgnoreCase(gender, "man")) {
            queryWrapper.eq("sex", SexEnum.WOMAN);
        }
        List<UserInfo> userInfoList = userInfoService.queryUserInfoList(queryWrapper);

        ArrayList<NearUserVo> nearUserVoList = new ArrayList<>();

        for (UserLocationVo locationVo : userLocationVoList) {
            //查询登录用户附近好友的结果中要排除自己
            if (locationVo.getUserId().longValue() == user.getId().longValue()) {
                continue;
            }

            for (UserInfo userInfo : userInfoList) {
                if (locationVo.getUserId().longValue() == userInfo.getUserId().longValue()) {
                    NearUserVo nearUserVo = new NearUserVo();
                    nearUserVo.setAvatar(userInfo.getLogo());
                    nearUserVo.setNickname(userInfo.getNickName());
                    nearUserVo.setUserId(userInfo.getUserId());
                    nearUserVoList.add(nearUserVo);
                    break;
                }
            }
        }

        return nearUserVoList;
    }

    public List<TodayBest> queryCardsList() {

        User user = UserThreadLocal.get();
        int count = 50;

        PageInfo<RecommendUser> pageInfo = this.recommendUserService.queryRecommendUserList(user.getId(), 1, count);
        List<RecommendUser> records = pageInfo.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            //默认推荐列表
            String[] defaultRecommendUserIds = StringUtils.split(defaultRecommendUsers, ",");
            for (String defaultRecommendUserId : defaultRecommendUserIds) {
                RecommendUser recommendUser = new RecommendUser(); //id.date.缘分值属性不需要,不赋值
                recommendUser.setUserId(Long.valueOf(defaultRecommendUserId));
                recommendUser.setToUserId(user.getId());
                pageInfo.getRecords().add(recommendUser);
            }
        }

        //从50个中随机10个
        int showCount = Math.min(10, records.size());//有可能取出来的records长度不足10个,避免索引越界
        List<RecommendUser> newRecords = new ArrayList<>();
        for (int i = 0; i < showCount; i++) {//不足十个全部取出
            //随机选出推荐的好友:注意随机数也可能会重复
            this.createRecommendUser(newRecords, records);
        }

        //查询好友信息
        HashSet<Long> userIds = new HashSet<>();
        for (RecommendUser record : newRecords) {
            userIds.add(record.getUserId());
        }

        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", userIds);
        List<UserInfo> userInfos = this.userInfoService.queryUserInfoList(queryWrapper);
        List<TodayBest> todayBests = new ArrayList<>();
        for (UserInfo userInfo : userInfos) {

            TodayBest todayBest = new TodayBest();
            todayBest.setId(userInfo.getUserId());
            todayBest.setAge(userInfo.getAge());
            todayBest.setAvatar(userInfo.getLogo());
            todayBest.setGender(userInfo.getSex().name().toLowerCase());
            todayBest.setNickname(userInfo.getNickName());
            todayBest.setTags(StringUtils.split(userInfo.getTags(), ','));
            todayBest.setFateValue(0L);

            todayBests.add(todayBest);
        }

        return todayBests;
    }

    //递归随机生成推荐好友,保证不重复
    private void createRecommendUser(List<RecommendUser> newRecords, List<RecommendUser> records) {

        RecommendUser recommendUser = records.get(RandomUtils.nextInt(0, records.size() - 1));
        if (!newRecords.contains(recommendUser)) { //不包含直接添加
            newRecords.add(recommendUser);
        } else {//包含则需要再抽取一次,开始递归
            createRecommendUser(newRecords, records);
        }
    }

    public Boolean likeUser(Long likeUserId) {
        User user = UserThreadLocal.get();
        String id = this.userLikeApi.saveUserLike(user.getId(), likeUserId);
        if (StringUtils.isEmpty(id)) {//保存失败
            return false;
        }

        if (this.userLikeApi.isMutualLike(user.getId(), likeUserId)) {
            //如果相互喜欢成为好友,将好友关系注册到环信
            this.imService.addContactUser(likeUserId);
        }
        return true;
    }

    public Boolean disLikeUser(Long likeUserId) {
        User user = UserThreadLocal.get();
        return this.userLikeApi.deleteUserLike(user.getId(), likeUserId);
    }
}
